package com.adwyxx.type;

import java.lang.reflect.*;
import java.util.List;
import java.util.Map;

/**
 * 参数化类型 {@link ParameterizedType}，即泛型。
 * 例如：{@code List<T>、Map<Integer, String>、List<? extends Number>} 带有类型参数的类型。也可以是自定义的。
 * 调用 getRawType() 与 getActualTypeArguments() 两个方法，就可以得到声明此参数化类型的类(java.lang.Comparable)和 实际的类型参数数组([? super T])，
 * 注意：? super T  又是一个 {@link WildcardType}类型。
 * <p>{@link ParameterizedType} 接口的三个方法：</p>
 * <ul>
 * <li>Type[] getActualTypeArguments()：获取泛型的类型参数的 Type 对象的数组，即：实际的泛型参数类型列表。如:Map<String,Integer> 的类型参数类型 -> [String,Integer]。</li>
 * <li>Type getOwnerType()：如果泛型所属于另一个类型，则返回其所属类型，否则返回 null。如：Map.Entry<K,V> 则 Entry 的所属类型 -> Map </li>
 * <li>Type getRawType()：获取泛型的实际类型。如 Map<K,V> -> Map</li>
 * </ul>
 *
 * @author Leo
 * @date 2024/8/19 15:25
 */
public class ParameterizedTypeDemo {
    /**
     * 自定义泛型类。
     * ParameterizedType#GetActualTypeArguments() 这个方法的返回值是一个Type的数组里面存的就是 K,V
     * @param <K> 参数类型
     * @param <V> 参数类型
     */
    static class InnerEntry<K,V> {
        private K key;
        private V value;

        public InnerEntry(K key,V value){
            this.key = key;
            this.value = value;
            System.out.println("key -> "+key);
            System.out.println("value -> "+value);

            Type type = this.getClass().getGenericSuperclass(); // generic 泛型
            System.out.println(type); // class java.lang.Object

            if(type instanceof ParameterizedType){
                ParameterizedType pt = (ParameterizedType) type;

                System.out.println("InnerEntry Owner Type -> "+pt.getOwnerType());

                Type[] actualTypeArguments = pt.getActualTypeArguments();
                for(Type t : actualTypeArguments) {
                    System.out.println(t.getTypeName());
                }
            }
        }
    }
    public static void test(List<ParameterizedTypeDemo> p1,Map<String, ParameterizedTypeDemo> p2,String p3,InnerEntry<Integer,String> p4) {

    }
    public static void main(String[] args) throws NoSuchMethodException {
        // Method[] methods = com.adwyxx.type_demo.ParameterizedTypeDemo.class.getMethods();
        // Method method = Arrays.stream(methods).filter(m -> m.getName().equals("test")).findFirst().get();
        Method method=ParameterizedTypeDemo.class.getMethod("test",List.class,Map.class,String.class,InnerEntry.class) ;
        // getParameters() --> 获取方法的参数列表
        Parameter[] parameters = method.getParameters();
        for(Parameter parameter : parameters){
            System.out.println("方法参数 "+parameter.getName()+" 的类型 -> "+parameter.getType().getTypeName());
            Type type = parameter.getParameterizedType();
            System.out.println("ParameterizedType -> "+type.getTypeName());
            System.out.println();
        }
        // getGenericParameterTypes() --> 获取方法的泛型类型参数
        Type[] types=method.getGenericParameterTypes();
        // --> java.util.List<com.adwyxx.type_demo.ParameterizedTypeDemo>
        // --> java.util.Map<java.lang.String, com.adwyxx.type_demo.ParameterizedTypeDemo>
        // --> java.lang.String
        // --> com.adwyxx.type_demo.ParameterizedTypeDemo$InnerEntry
        for(Type type : types){
            System.out.println("方法参数（泛型参数）的类型 -> "+type.getTypeName());
            System.out.println("----------"+type.getTypeName()+"----------");
            if(type instanceof ParameterizedType) {
                ParameterizedType pt = (ParameterizedType) type; // 参数化类型可以使用 ParameterizedType 接口强制转换
                // 1. getRawType() 方法：获取泛型的实际类型
                System.out.println("泛型的实际类型 -> " + pt.getRawType().getTypeName());

                // 2. getOwnerType() 方法：获取泛型所属的类型
                if(pt.getOwnerType() != null){
                    System.out.println("泛型所属的类型 -> " + pt.getOwnerType().getTypeName());
                }

                // 3. getActualTypeArguments() 方法：获取泛型的类型参数的 Type 对象的数组
                Type[] actualTypeArguments = pt.getActualTypeArguments();
                System.out.println("泛型参数的类型 ：");
                for (Type actualTypeArgument : actualTypeArguments) {
                    System.out.println("    + " + actualTypeArgument.getTypeName());
                }

            } else {
                System.out.println(type.getTypeName()+" -> 非参数化类型");
            }
            System.out.println("----------" + type.getTypeName() + "----------");
            System.out.println();
        }

        Class clazz = InnerEntry.class;
        System.out.println(clazz.getTypeName());
        Type[] typeParameters =  clazz.getTypeParameters();
        for (Type typeParameter : typeParameters) {
            System.out.println("泛型类 "+clazz.getSimpleName()+" 的类型参数 -> " + typeParameter.getTypeName());
        }
        // 泛型类 InnerEntry 的类型参数 -> K
        // 泛型类 InnerEntry 的类型参数 -> V
        InnerEntry entry = new InnerEntry("key","value");
        // 获取父类的泛型类型对象（ParameterizedType）,如果父类不是泛型类，那么返回普通类型
        Type et = entry.getClass().getGenericSuperclass();
        if(et instanceof ParameterizedType){
            ParameterizedType pt = (ParameterizedType) et;
            System.out.println("InnerEntry super class ParameterizedType -> "+pt.getOwnerType());
            Type[] actualTypeArguments = pt.getActualTypeArguments();
            for(Type t : actualTypeArguments) {
                System.out.println(t.getTypeName());
            }
        }
    }
}